import {
	IAgentStatus,
	IMembers,
	IStreamMode,
	IUser,
	ICollectionVariable,
	INITParams,
	LoginResponseProps,
	IValidGroups,
	ILoginData,
	ILayout,
	ICurrentTab,
	IStreamLabel,
	ISessionEventKey,
	ICallUserData,
	IOperationName,
	IOperationType,
	IOtherWork,
	IChiefGroups,
	IVariableList,
	Tentry,
	IAnswerMediaData,
	Scene,
	SessionClient,
	IJoinedMembers
	// IUpgradeData
} from './interface';

import { sendCustomizeMessage } from '@/views/Context/utils/requestBusiness';

import EventEmit, { IEvent } from './Event';
import Video from './Video';
import Network from './Network';
import Session from './Session';
import MediaDevice from './MediaDevice';
import Configure from './Configure';
import QualityTesting from './QualityTesting';

import Response, { Status, Code, EevntType } from './Response';

import {
	initWithEncrypt,
	AgentLoginSystem,
	checkIn,
	getQueueInfo,
	checkOut,
	ready,
	answer,
	renderStream,
	hangup,
	rejectSession,
	unReady,
	initWithLoginData,
	logout,
	closePage,
	startVideo,
	answerImCall,
	requestUpgrade,
	acceptUpgrade,
	rejectUpgrade,
	cancelUpgrade,
	answerMediaCall,
	startMedia,
	afterWorkEnd,
	getSessionMembers,
	sendStartVideoProgressMessage,
	getNewToken,
	syncSessionSummary
} from './IVCS';
import Logger from './Logger';
import { backgroundImageRespone, watermarkImageRespone } from './errorResponse';
import { validateAms, validateImage, compressFile, filterBackgroundList, validateArrayLength, filterWaterMarkList, filterStreamInfo } from './utils';
import { createBackgroundImage, getBackgroundList, validateChiefLoginSystem, applyBackgroundImage, deleteBackgroundImage, checkedAgentOtherWork, saveOtherWork } from './Api';

import { uploadFile } from '@/utils/upload';
import clog from './CLog';
import AgentDao from './dao/AgentDao';
import { createWaterMark, delWaterMark, getWaterMarkList, putWaterMark } from '@/api';
import Message from './Message';
import AgentController, { BusinessCmd } from './controller/AgentController';
import MediaDeviceController from './controller/MediaDeviceController';
import MediaStreamConfigure from './config/MediaStreamConfigure';
import MediaDeviceDao from './dao/MediaDeviceDao';
import MediaStreamController from './controller/MediaStreamController';
import BusinessController from './controller/BusinessController';
import { IFormBusiness } from './dao/BusinessDao';
import Client from './libs/Client';
import { joinSessionWithSessionId } from '@/utils/lib';
import { updateMediaRenderStatus } from './Api';

export type { ICollectionVariable, IStreamMode, ILayout, ICurrentTab, IOtherWork };

export { IOperationName, IOperationType, IEvent, Code, Video };

class Agent extends Session {
	public agentMembers: Map<string, IMembers>;
	public customerMembers: Map<string, IMembers>;
	public allMembers: Map<string, IMembers>;
	private static instance: Agent | null;
	public user: IUser | null;
	public checkedGroups: { id: number; name: string }[];
	public agentStatus: IAgentStatus;
	// public mediaDevices: MediaDevice;
	public mediaDeviceController: MediaDeviceController = new MediaDeviceController();
	public mediaStreamController: MediaStreamController = new MediaStreamController();
	public businessController = new BusinessController();
	private agentController: AgentController = new AgentController();
	public configure: Configure;
	public qualityTesting: QualityTesting;
	public rootContainer: HTMLElement;
	public validGroups: IValidGroups[];
	public isChiefsGroups: IChiefGroups[];
	public static logger: Logger;
	public token: string;
	public checkedChiefGroups: { id: number; name: string }[];
	public customizeLocalStream: MediaStream | null;
	public logAmsId: string = '';
	public amsNetworkTips: string; // ams连接异常提示
	public waitingInfoTips: string; // 排队信息提示
	public useAsWidget: boolean = true; // 是否作为小部件使用

	public renderedLabel: Map<string, any> = new Map();

	public agentDao = new AgentDao();

	static getInstance(): Agent {
		// 判断系统是否已经有这个单例
		if (Agent.instance === null) {
			Agent.instance = new Agent();
		}
		return Agent.instance; // 单例模式
	}
	constructor() {
		super();
		this.agentMembers = new Map();
		this.customerMembers = new Map();
		this.allMembers = new Map();
		this.user = null;
		this.rootContainer = document.body;
		this.checkedGroups = [];
		// this.mediaDevices = new MediaDevice();
		this.configure = new Configure();
		this.qualityTesting = new QualityTesting();
		this.agentController = new AgentController();

		// this.mediaDevices.init();
		// this.mediaDevices.initEvent();
		this.token = '';
		this.validGroups = [];
		this.isChiefsGroups = [];
		this.checkedChiefGroups = [];
		this.customizeLocalStream = null;
		Agent.logger = new Logger();
		this.agentStatus = {
			logged: true, //登入
			ready: false, //就绪
			otherWork: false, //小休
			checkIn: false, //签入
			isChief: false,
			afterWork: false
		};
		this.mediaDeviceController.init();
		// this.onbeforeunload();
		// this.onunload();
		this.amsNetworkTips = '';
		this.waitingInfoTips = '';
	}

	public init(serviceUrl: string, params: INITParams) {
		const {
			chatBoxHidden,
			userInfoHidden,
			bizPannelHidden,
			qualityTestingResultHidden,
			layoutConfigHidden,
			languageConfigHidden,
			watermarkConfigHidden,
			acceptCallConfigHidden,
			managementMenuHidden,
			agentManagemenMenuHidden,
			isCallProgressHidden,
			isImagePreviewHidden,
			headerMenus = [],
			ignoreTools,
			isRecordHidden = false,
			isNotifyCustomerMediaUpgrade,
			disableAudioAnswerToVideoCall,
			deviceConfigHidden = false,
			virtualBackgroundConfigHidden = false,
			floatAlertConfigHidden = false,
			awsFileUrl
		} = params;
		/** 初始化用户偏好 */
		this.configure.setPreferenceSettings({
			chatBoxHidden,
			userInfoHidden,
			bizPannelHidden,
			qualityTestingResultHidden,
			layoutConfigHidden,
			languageConfigHidden,
			watermarkConfigHidden,
			acceptCallConfigHidden,
			managementMenuHidden,
			agentManagemenMenuHidden,
			isCallProgressHidden,
			isImagePreviewHidden,
			headerMenus,
			ignoreTools,
			isRecordHidden,
			isNotifyCustomerMediaUpgrade,
			disableAudioAnswerToVideoCall,
			deviceConfigHidden,
			virtualBackgroundConfigHidden,
			floatAlertConfigHidden
		});

		/** 设置访问服务地址 */
		this.configure.setServiceUrl(serviceUrl);
		Agent.logger.info('service url:', serviceUrl);

		// aws存储文件方式，则设置资源文件加载前缀url
		if (typeof awsFileUrl !== 'undefined') {
			this.configure.setAwsFileUrl(awsFileUrl);
			Agent.logger.info('aws file url:', awsFileUrl);
		}
	}

	/** 初始化创建容器 */
	public createView(container: string, useAsWidget: boolean = true) {
		if (!document.getElementById(container)) {
			Agent.logger.error('root view is undefined, view append body');
			// this.event.setServiceEventListener({ type: 'init', event: 'error' }, { code: 404, message: 'root container is undefined' });
		} else {
			this.rootContainer = document.getElementById(container)!;
			this.useAsWidget = useAsWidget;
		}
	}

	/** 初始化事件监听 */
	public addEventListener(ack: (info: any) => void) {
		EventEmit.addServiceEvent(ack);
	}

	/** 移除事件监听 */
	public removeEventListener() {
		EventEmit.removeServiceEvent();
	}

	/** 移除设备事件监听 */
	public removeDeviceEventListener() {
		EventEmit.removeDeviceEventLinstener();
	}

	/** 初始化设备监听 */
	public addDeviceEventLinstener(ack: (info: any) => void) {
		EventEmit.addDeviceEventLinstener(ack);
	}

	/** 移除三方邀请监听 */
	public removeInviteEventListener() {
		EventEmit.removeInviteEvent();
	}

	/** 初始化三方邀请监听 */
	public addInviteEventLinstener(ack: (info: any) => void) {
		EventEmit.addInviteEventListener(ack);
	}

	/**
	 * 设置坐席状态
	 * @param status 坐席状态
	 */
	public setAgentStatus = (status: IAgentStatus) => {
		this.agentStatus = { ...this.agentStatus, ...status };
		this.setResponse(IEvent.SET_AGENT_STATUS, Response.SET_AGENT_STATUS_EVENT, this.agentStatus);
		Agent.logger.info('agent status:', this.agentStatus);
	};
	/**
	 * 设置用户信息
	 * @param user
	 */
	public setUser = (user: IUser) => {
		this.user = { ...this.user, ...user };
		Agent.logger.info(`setUser: ${JSON.stringify(this.user)}`);
	};

	public setCheckedGroups = (groups: { name: string; id: number }[]) => {
		this.checkedGroups = groups;
		Agent.logger.info(`setCheckedGroups:`, this.checkedGroups);
	};

	public agentJoinSession = (clientId: string, agent: IMembers) => {
		this.agentMembers.set(clientId, agent);
		Agent.logger.info(`agentJoinSession:${clientId} --- ${JSON.stringify(agent)}`);
	};

	public customerJoinSession = (clientId: string, customer: IMembers) => {
		this.customerMembers.set(clientId, customer);
		Agent.logger.info(`customerJoinSession:${clientId} --- ${JSON.stringify(customer)}`);
	};

	private filterMembers = () => {
		const members = [...this.allMembers.values()];
		members.map(member => {
			if (member.label.indexOf('customer') > -1) {
				this.customerJoinSession(member.clientId, member);
			} else if (member.label.indexOf('agent') > -1) {
				this.agentJoinSession(member.clientId, member);
			}
		});
	};

	public membersJoinSession = (clientId: string, members: IMembers) => {
		this.allMembers.set(clientId, members);
		this.filterMembers();
		Agent.logger.info(`membersJoinSession:${clientId} --- ${JSON.stringify(members)}`);
	};

	public removeMembers = (clientId: string) => {
		if (this.hasInMembers(clientId)) {
			this.allMembers.delete(clientId);
		}
		if (this.customerMembers.has(clientId)) {
			this.customerMembers.delete(clientId);
		}
		if (this.agentMembers.has(clientId)) {
			this.agentMembers.delete(clientId);
		}
	};

	/** 从 memerbs 中获取，用户标签 */
	public getMembersLabel = (label: string) => {
		if (label.indexOf('customer') > -1) {
			return 'customer';
		} else if (label.indexOf('agent') > -1) {
			return 'agent';
		} else {
			return null;
		}
	};

	public clear = () => {
		this.agentMembers.clear();
		this.allMembers.clear();
		this.customerMembers.clear();
		this.user = null;
		this.sessionEnd();
		if (!this.agentStatus.checkIn) {
			this.removeCallProgressTimer();
		}
	};

	public getAgentName = (clientId: string) => {
		const client = this.getAgentInMemebrs(clientId);
		return client?.userName;
	};

	private hasInMembers = (clientId: string) => {
		return this.allMembers.has(clientId);
	};

	private getAgentInMemebrs = (clientId: string) => {
		if (this.hasInMembers(clientId)) {
			return this.agentMembers.get(clientId);
		}
		return null;
	};

	/** 更新坐席属性状态 */
	public setAgentStream = (clientId: string, mode: IStreamMode) => {
		const client = this.getAgentInMemebrs(clientId);
		client && this.agentMembers.set(clientId, { ...client, streamMode: mode });
	};

	public setAgentScreenSyncMode = (clientId: string, isScreenSyncMode: boolean) => {
		const client = this.getAgentInMemebrs(clientId);
		client && this.agentMembers.set(clientId, { ...client, isScreenSyncMode: isScreenSyncMode });
	};

	public setMuteStatus = (clientId: string, muteStatus: boolean) => {
		const client = this.getAgentInMemebrs(clientId);
		client && this.agentMembers.set(clientId, { ...client, muteStatus: muteStatus });
	};

	public setAudioStatus = (clientId: string, audioOnly: boolean) => {
		const client = this.getAgentInMemebrs(clientId);
		client && this.agentMembers.set(clientId, { ...client, audioOnly: audioOnly });
	};

	/** 坐席登录系统 */
	public async loginSystem() {
		const { loginData, defaultMediaOptions, serviceUrl } = this.configure;
		const { username, password, org } = loginData;

		try {
			const data = await initWithEncrypt(serviceUrl, username, password, org, defaultMediaOptions);
			console.log('initWithEncrypt:', data);
			const { isInitPwd, pwdUpdateDeadline } = data;
			const ticket = await AgentLoginSystem();
			this.setUserLoginResponse(data);
			this.setTicketInfo(ticket);
			this.setAgentStatus({ ...this.agentStatus, logged: true });
			this.initBaseEvent();
			this.initUserProfile();
			this.setResponse(IEvent.LOGIN, Response.LOGIN_SUCCESS, { ...data, ...ticket });
			this.agentController.fetchAllGroupsWithOrg();
			this.logAmsId = ticket.id || '';
			this.getUnfinishedSummary();
			// 初次登录账号，在登录账号时系统提醒修改初始密码，并强制进入修改初始密码页面
			if (isInitPwd === 'Y') {
				setTimeout(() => {
					this.showChangePasswordModal();
				}, 100);
			}
			// 超期前2周内，用户每次登录成功提示用户更新密码，弹出提示弹框，弹框文案显示“您当前使用的登录密码还有xx天到期，请及时更新登录密码”，弹框显示“我知道了”和“修改密码”两个按钮。
			if (pwdUpdateDeadline) {
				setTimeout(() => {
					this.needUpdatePassword(pwdUpdateDeadline);
				}, 100);
			}
		} catch (error: any) {
			Agent.logger.error('login system error', error);
			this.setResponse(IEvent.LOGIN, Response.LOGIN_ERROR, error as any);
		}
	}

	/** sso 登录 */
	public async ssologinSystem(logindata: any) {
		console.log('ssologinSystem ', logindata);
		try {
			const data: any = await initWithLoginData(this.configure.serviceUrl, logindata, this.configure.defaultMediaOptions);
			const ticket: any = await AgentLoginSystem();
			this.setUserLoginResponse(data);
			this.setToken(logindata?.accessToken || '');
			this.setAgentStatus({ ...this.agentStatus, logged: true });
			this.initBaseEvent();
			this.initUserProfile();
			this.setResponse(IEvent.LOGIN, Response.LOGIN_SUCCESS, { ...data, ...ticket });
			const { isInitPwd, pwdUpdateDeadline } = logindata.tokenData.data;
			// 初次登录账号，在登录账号时系统提醒修改初始密码，并强制进入修改初始密码页面
			if (isInitPwd === 'Y') {
				setTimeout(() => {
					this.showChangePasswordModal();
				}, 100);
			}
			// 超期前2周内，用户每次登录成功提示用户更新密码，弹出提示弹框，弹框文案显示“您当前使用的登录密码还有xx天到期，请及时更新登录密码”，弹框显示“我知道了”和“修改密码”两个按钮。
			if (pwdUpdateDeadline) {
				setTimeout(() => {
					this.needUpdatePassword(pwdUpdateDeadline);
				}, 100);
			}
		} catch (error: any) {
			Agent.logger.error('sso login system error', error);
			this.setResponse(IEvent.LOGIN, Response.LOGIN_ERROR, error as any);
		}
	}

	/** 坐席签入分组 */
	public async checkinSystem(groups: { id: number; name: string }[]) {
		const groupIds = groups.map(item => item.id);
		console.log('groupIds:', groupIds);

		if (groupIds.length === 0) {
			this.setResponse(IEvent.CHECK_IN, Response.CHECK_OUT_PARAMS_ERROR, null);
			return;
		}
		try {
			const data = await checkIn(groupIds);
			let groupsChief: any[] = [];
			if (data.code === 200) {
				this.setAgentStatus({ ...this.agentStatus, checkIn: true });
				getQueueInfo(
					progress => this.watchProgress(progress),
					() => {
						this.removeCallProgressTimer();
					}
				);
				this.setCheckedGroups(groups);
				// 设置定时查询排队任务
				if (!this.callProgressTime) {
					let timer = setInterval(() => {
						getQueueInfo(
							progress => this.watchProgress(progress),
							() => {
								this.removeCallProgressTimer();
							}
						);
					}, 2000);
					this.setCallProgressTimer(timer);
				}
				groupIds.forEach(async (groupId, index) => {
					const data = await validateChiefLoginSystem(this.user!.id!, groupId);
					groupsChief = [...groupsChief, data];
					if (index + 1 === groupIds.length) {
						this.setIsChiefs(groupsChief);
						if (groupsChief.filter(item => item.isTeamLeader).length > 0) {
							this.setAgentStatus({ ...this.agentStatus, isChief: true });
						}
					}
				});
				this.setResponse(IEvent.CHECK_IN, Response.CHECK_IN_SUCCESS, groups);
				return { code: 200, message: 'checkin success', data: groups };
			}
		} catch (error) {
			Agent.logger.error('checkin system error', error);
			this.setResponse(IEvent.CHECK_IN, Response.CHECK_IN_ERROR, error as any);
			return { code: 400, message: 'checkin failed', data: error };
		}
	}

	/** 坐席签出分组 */
	public async checkoutSystem() {
		if (this.sessionId) {
			this.setResponse(IEvent.CHECK_OUT, Response.CHECK_OUT_ERROR, null);
			return { code: 400, message: 'checkout failed user in session', data: null };
		}
		try {
			const groupIds = this.checkedGroups.map(item => item.id);
			const data = await checkOut(groupIds);
			if (data.code === 200) {
				this.removeCallProgressTimer();
				this.setCheckedGroups([]);
				this.setCallProgressGroups([]);
				this.updateCallProgress(0);
				this.setAgentStatus({ ...this.agentStatus, checkIn: false, isChief: false });
				this.setResponse(IEvent.CHECK_OUT, Response.CHECK_OUT_SUCCESS, data);
				return { code: 200, message: 'checkout success', data };
			} else {
				this.setResponse(IEvent.CHECK_OUT, Response.CHECK_OUT_ERROR, data);
				return { code: 400, message: 'checkout failed', data };
			}
		} catch (error) {
			Agent.logger.error('checkout system error', error);
			this.setResponse(IEvent.CHECK_OUT, Response.CHECK_OUT_ERROR, error as any);
			return { code: 400, message: 'checkout failed', data: error };
		}
	}

	/** 坐席就绪 */
	public async agentReady() {
		if (this.sessionId) {
			this.setResponse(IEvent.READY, Response.READY_ERROR_SESSION_EXCEPTION, null);
			return { code: 400, message: 'user in session', data: null };
		}

		try {
			const data = await ready();
			if (data.code === 200) {
				this.setAgentStatus({ ...this.agentStatus, ready: true, otherWork: false });
				this.setResponse(IEvent.READY, Response.READY_SUCCESS, data.data);
				return data;
			} else {
				return { code: 400, message: 'ready failed', data };
			}
		} catch (error) {
			Agent.logger.error('ready system error', error);
			this.setResponse(IEvent.READY, Response.READY_ERROR, error as any);
			return { code: 400, message: 'ready failed', data: error };
		}
	}

	/** 坐席取消就绪 */
	public async agentUnReady() {
		if (!validateAms(Network.amsStatus)) {
			this.setResponse(IEvent.UNREADY, Response.UNREADY_ERROR_AMS_EXCEPTION, null);
			return { code: 400, message: 'ams connected failed', data: null };
		}
		if (this.sessionId) {
			this.setResponse(IEvent.UNREADY, Response.UNREADY_ERROR_SESSION_EXCEPTION, null);
			return { code: 400, message: 'user in session', data: null };
		}

		try {
			const data = await unReady();
			if (data.code === 200) {
				this.setAgentStatus({ ...this.agentStatus, ready: false });
				this.setResponse(IEvent.UNREADY, Response.UNREADY_SUCCESS, this.agentStatus);
				return data;
			} else {
				return { code: 400, message: 'unReady failed', data };
			}
		} catch (error) {
			Agent.logger.error('unReady system error', error);
			this.setResponse(IEvent.UNREADY, Response.UNREADY_ERROR, error as any);
			return { code: 400, message: 'unReady failed', data: error };
		}
	}

	//结束话后整理
	public async closeAfterWork() {
		try {
			const data = await afterWorkEnd();
			console.log('afterWorkEnd ', data);
			if (data.code === 200) {
				this.setAgentStatus({ ...this.agentStatus, afterWork: false });
				this.setResponse(IEvent.AFTER_WORK_END, Response.AFTER_WORK_END_SUCCESS, this.agentStatus);
				return data;
			}
		} catch (error) {
			Agent.logger.error('afterWorkEnd system error', error);
			this.setResponse(IEvent.AFTER_WORK_END, Response.AFTER_WORK_END_ERROR, error as any);
			return { code: 400, message: 'afterWorkEnd failed', data: error };
		}
	}

	public async joinSessionWithChief() {
		try {
			const username = this.user?.userName || '';
			const agentLabel = 'agent' + username + '-' + Math.round(Math.random() * (1 - 10000) + 10000);
			const bizScenarioId = this.bizScenarioId ? this.bizScenarioId : this.userData?.businessflowId || '';
			const data = await joinSessionWithSessionId(this.sessionId, bizScenarioId);
			this.setAgentStatus({ ...this.agentStatus, isChief: true });
			this.initJoinSessionEvent();

			if (!this.sessionId) return;

			const { sessionData } = data;

			console.log('this.sessionId:', this.sessionId, data);
			this.setSessionMembers(sessionData.members as IJoinedMembers[]);
			this.setRoomId(sessionData.roomId);
			this.setClientID(sessionData.clientId);

			const mediaOptions = {
				audioConstraints: { ...MediaStreamConfigure.defaultMediaOptions.cameraStreamAudioConstraints, deviceId: MediaDeviceDao.audioInputDeviceId },
				videoConstraints: { ...MediaStreamConfigure.defaultMediaOptions.cameraStreamVideoConstraints, deviceId: MediaDeviceDao.videoInputDeviceId },
				publishOptions: MediaStreamConfigure.defaultMediaOptions.cameraPublishOptions
			};

			const startVideoData = await startMedia(agentLabel, this.acceptCallMode.receiveMediaType, this.customizeLocalStream, mediaOptions);

			if (startVideoData?.code === 200) {
				if (this.acceptCallMode.receiveMediaType !== startVideoData.data.realMediaType) {
					Message.info('未检测到摄像头，自动切换为语音接听！');
				}
				this.setAcceptCallMode({ ...this.acceptCallMode, receiveMediaType: startVideoData.data.realMediaType });
				this.setParticipantId(startVideoData.data.participantId);
				this.setPublicationId(startVideoData.data.publicationId);
				// 获取业务流程
				if (bizScenarioId) {
					this.setBizScenarioId(bizScenarioId);
					await this.fetchGroupWithBizscenariosID(parseInt(this.bizScenarioId));
				}
				/** 监听加入会话后事件 */
				this.initJoinedSessionEvent();
				this.onSessionRecordCrashListener();
				this.saveCurrentAgentStream();
			}
			this.setResponse(IEvent.OBSERVER_JOIN_SESSION, Response.OBSERVER_JOIN_SESSION_SUCCESS, data);
			console.log('startVideoData:', startVideoData);
		} catch (error) {
			this.setResponse(IEvent.OBSERVER_JOIN_SESSION, Response.OBSERVER_JOIN_SESSION_ERROR, error as any);
		}
	}

	public async answer() {
		try {
			// if (!validateAms(Network.amsStatus)) {
			// 	this.setResponse(IEvent.ANSWER, Response.ANSWER_ERROR_AMS_EXCEPTION, null);
			// 	return { code: 400, message: 'answer failed ams connected failed', data: null };
			// }

			const { loginData } = this.configure;
			const mediaOptions = {
				audioConstraints: { ...MediaStreamConfigure.defaultMediaOptions.cameraStreamAudioConstraints, deviceId: MediaDeviceDao.audioInputDeviceId },
				videoConstraints: { ...MediaStreamConfigure.defaultMediaOptions.cameraStreamVideoConstraints, deviceId: MediaDeviceDao.videoInputDeviceId },
				publishOptions: MediaStreamConfigure.defaultMediaOptions.cameraPublishOptions
			};

			// this.mediaDeviceController.setDefaultMediaDeviceID();

			// const data = await answer(loginData.username, this.acceptCallMode.receiveMediaType, this.customizeLocalStream, mediaOptions);

			const answerData = await answerMediaCall(this.acceptCallMode.receiveMediaType);
			/** 监听加入会话前事件 */
			this.initJoinSessionEvent();
			this.initJoinedSessionEvent();
			console.log(answerData, 'answerData success');
			if (answerData?.code === 200) {
				let agentLabel = 'agent' + this.user?.userName + '-' + Math.round(Math.random() * (1 - 10000) + 10000);

				// this.startVideoProgressMessage(answerData.data.sessionData.clientId, agentLabel, 'permission');
				// 设置自动双录标识
				this.setIsAutoSystemRecord(answerData.data.sessionData.isAutoSystemRecord);
				this.setAcceptMediaCallData(answerData.data);

				if (!this.sessionId) return;

				console.log('this.sessionId:', this.sessionId);

				const startVideoData = await startMedia(agentLabel, this.acceptCallMode.receiveMediaType, this.customizeLocalStream, mediaOptions);

				console.log(startVideoData, 'startVideoData success');
				if (startVideoData?.code === 200) {
					if (this.acceptCallMode.receiveMediaType !== startVideoData.data.realMediaType) {
						Message.info('未检测到摄像头，自动切换为语音接听！');
					}
					this.setAcceptCallMode({ ...this.acceptCallMode, receiveMediaType: startVideoData.data.realMediaType });
					this.setParticipantId(startVideoData.data.participantId);
					this.setPublicationId(startVideoData.data.publicationId);
					/** 监听加入会话后事件 */
					// this.initJoinedSessionEvent();
					this.onSessionRecordCrashListener();
					this.setResponse(IEvent.ANSWER, Response.ANSWER_SUCCESS, answerData.data);
				} else {
					this.setResponse(IEvent.ANSWER, Response.ANSWER_SUCCESS, startVideoData.data);
				}
			} else {
				this.setResponse(IEvent.ANSWER, Response.ANSWER_PARAMS_ERROR, answerData);
			}
		} catch (error) {
			console.log('answer error:', error);
			this.setResponse(IEvent.ANSWER, Response.ANSWER_ERROR, error as any);
			updateMediaRenderStatus(this.sessionId, false);
		}
	}
	/** 渲染流 */
	public async renderStream(streamLabel: string, videoId: string) {
		try {
			if (!this.renderedStreamMap.has(videoId)) {
				const data = await renderStream(streamLabel, videoId);
				if (data?.code === 200) {
					const stream = this.getRenderStream(videoId);
					// await this.mediaDeviceController.switchSpeaker(videoId);
					if (stream) {
						// this.setRenderedStream(videoId, stream);
					}
					this.setResponse(IEvent.ANSWER, Response.RENDER_SUCCESS, data);
					return { code: 200, message: 'render media success', data: stream };
				}
			} else {
				const stream = this.renderedStreamWidthID(videoId);
				if (stream) {
					this.setResponse(IEvent.RENDER, Response.RENDER_SUCCESS, stream);
					return { code: 200, message: 'render media success', data: stream };
				} else {
					this.setResponse(IEvent.RENDER, Response.RENDER_PARAMS_ERROR, null);
					return { code: 400, message: 'render media failed', data: stream };
				}
			}
		} catch (error) {
			this.setResponse(IEvent.RENDER, Response.RENDER_ERROR, error as any);
			return { code: 400, message: 'render media failed', data: error };
		}
	}

	/** 拒绝会话 */
	public async rejectSession() {
		try {
			const data = await rejectSession();
			if (data?.code === 200) {
				this.setResponse(IEvent.REJECT_SESSION, Response.REJECT_SESSION_SUCCESS, data);
				this.sessionEnd();
				if (!this.agentStatus.checkIn) {
					this.removeCallProgressTimer();
				}
			}
		} catch (error) {
			this.setResponse(IEvent.REJECT_SESSION, Response.REJECT_SESSION_ERROR, error as any);
		}
	}

	/** 挂断会话 */
	public async hangup(reason: { code?: number; reason?: string; type?: string }) {
		if (this.agentStatus.afterWork) {
			return;
		}
		try {
			this.agentController.clearSessionClient();
			window.sessionStorage.removeItem('sessionID');
			const data = await hangup(reason);
			//  type:string()},默认传值为{}, 转接挂断{type:'' || 'transfer' || 'multiple'}
			console.log('hangup call', reason, 'result:', data);
			if (data.data.result && data.data.result.state === 'afterWork') {
				this.setAgentStatus({ ...this.agentStatus, afterWork: true });
				this.setResponse(IEvent.AFTER_WORK_START, Response.AFTER_WORK_END_SUCCESS, data.data);
			} else {
				this.agentController.clearProfiles();
			}
			if (data?.code === 200) {
				this.setResponse(IEvent.HANG_UP, Response.HANG_UP_SUCCESS, data.data);
			}
		} catch (error) {
			this.setResponse(IEvent.HANG_UP, Response.HANG_UP_ERROR, error as any);
			console.log('hangup error', reason, error);
		} finally {
			this.sessionEnd();
			this.renderedLabel.clear();

			if (!this.agentStatus.checkIn) {
				this.removeCallProgressTimer();
			}
			this.removeSessionListenerEvent();
			this.businessController.clearFormDetail();
			clog.setSessionId('');
			this.qualityTesting.clearQualityTestingResult();
			// 清空人工工作流
			this.agentController.setHumanflowSteps(null);
			// 获取未完成会话小结状态
			this.getUnfinishedSummary();
			// clear agent members
			this.agentMembers.clear();
		}
	}

	public startVideoProgressMessage(clientId: string, agentLabel: string, status: 'idle' | 'permission' | 'publish' | 'published') {
		// 发送开画进度
		let clientInfo: SessionClient = {
			fromUser: {
				name: this.user?.userName || '',
				avatar: '',
				isRobot: false,
				customerRole: '',
				role: 'agent'
			},
			data: {
				label: agentLabel,
				clientId: clientId,
				role: 'agent',
				isRobotStream: false,
				status,
				businessType: 'notice_media_progress'
			}
		};
		this.agentController.setSessionClient(clientInfo);
		const client = this.agentController.getSessionClientWithLabel(agentLabel);
		if (client) {
			this.setResponse(IEvent.STREAM_ADD, Response.STREAM_ADD_EVENT, client);
		}
		sendStartVideoProgressMessage(agentLabel, clientId, status);
	}

	/** 根据videoID 查找已经渲染的流 */
	public async renderedStreamWidthID(id: string) {
		if (!this.renderedStreamMap.has(id)) return;
		const stream = this.renderedStreamMap.get(id);
		const video = document.getElementById(id) as HTMLVideoElement;
		if (video && stream) {
			video.srcObject = stream;
			// await this.mediaDeviceController.switchSpeaker(id);
		}
		return stream;
	}

	public setCheckedChiefGroups(group: { id: number; name: string }) {
		this.checkedGroups = [...this.checkedChiefGroups, group];
	}

	/** 设置可签入的有效分组 */
	public setvalidGroups = (groups: IValidGroups[]) => {
		this.validGroups = groups;
	};

	/** 设置属于班组长的分组 */
	public setIsChiefs = (groups: IChiefGroups[]) => {
		this.isChiefsGroups = groups.filter(item => item.isTeamLeader);
	};

	/** 设置登录返回的数据 */
	public setUserLoginResponse(data: LoginResponseProps) {
		const { token = '', groupsList = [], user = {} } = data;
		this.setToken(token);
		this.setUser(user);
		this.setvalidGroups(groupsList);
		console.log(data);
	}

	/** 上传背景图片 */
	public async uploadBackground(file: File) {
		try {
			const { code, data, message } = await validateImage(file, 20);
			if (code === 200) {
				const file = await compressFile(data, 5, true, 0.92, 480, 320);
				const prevImage = await uploadFile(file as File);
				const realImage = await uploadFile(data as File);
				if (prevImage && realImage) {
					if (validateArrayLength(this.agentDao.getBackgroundList(), 30)) {
						await createBackgroundImage({ url: realImage?.url, abbreviatedUrl: prevImage?.url, fileName: prevImage?.name || '', isDefault: false, type: 'normal' });
						this.setResponse(IEvent.BACKGROUND, Response.CREATE_BACKGROUND_SUCCESS, data);
						return { data: { code: 200, data: { prevImage, realImage }, message: 'uploadBackground success' } };
					} else {
						this.setResponse(IEvent.BACKGROUND, Response.CREATE_BACKGROUND_COUNT_ERROR, data);
						return { data: { code: 400, data: { prevImage, realImage }, message: 'uploadBackground  failed' } };
					}
				} else {
					this.setResponse(IEvent.BACKGROUND, Response.CREATE_BACKGROUND_API_ERROR, data);
					return { data: { code: 400, data: null, message: 'uploadBackground failed' } };
				}
			} else {
				if (code === 501) {
					this.setResponse(IEvent.BACKGROUND, Response.FILE_TYPE_ERROR, { code, data, message });
				} else if (code === 502) {
					this.setResponse(IEvent.BACKGROUND, Response.FILE_SIZE_ERROR, { code, data, message });
				} else if (code === 503 || code === 504) {
					this.setResponse(IEvent.BACKGROUND, Response.IMAGE_SIZE_ERROR, { code, data, message });
				}

				return { data: { code, data, message } };
			}
		} catch (error) {
			this.setResponse(IEvent.BACKGROUND, Response.CREATE_BACKGROUND_ERROR, error as any);
			return { data: { code: 400, data: null, message: 'uploadBackground failed' } };
		} finally {
			this.getBackgroundList();
		}
	}
	/** 获取背景图片列表 */
	public async getBackgroundList() {
		try {
			const { data } = await getBackgroundList({ page: 1, pageSzie: 30 });
			if (data.code === 200) {
				this.agentDao.setBackgroundId(data.data.selectedId || -2);
				const list = data.data.data
					.filter((background: any) => background.type !== 'no' && background.type !== 'fuzzy')
					.map((item: any) => {
						return { ...item, url: this.configure.replaceStaticUrl(item.url) || '', abbreviatedUrl: this.configure.replaceStaticUrl(item.abbreviatedUrl) || '' };
					});
				this.agentDao.setBackgroundList(filterBackgroundList(list));
				this.setResponse(IEvent.BACKGROUND, Response.GET_BACKGROUND_LIST_SUCCESS, data.data);
			} else {
				this.setResponse(IEvent.BACKGROUND, Response.GET_BACKGROUND_LIST_ERROR, data.data);
			}
		} catch (error) {
			this.setResponse(IEvent.BACKGROUND, Response.GET_BACKGROUND_LIST_API_ERROR, error as any);
		}
	}

	/** 应用背景图片 */
	public async applyBackground() {
		try {
			const data = await applyBackgroundImage({ backgroundId: this.agentDao.getBackgroundId() });
			this.setResponse(IEvent.BACKGROUND, Response.APPLY_BACKGROUND_SUCCESS, data);
		} catch (error) {
			this.setResponse(IEvent.BACKGROUND, Response.APPLY_BACKGROUND_ERROR, error as any);
		}
	}

	/** 删除背景图片 */
	public async deleteBackground(id: number) {
		try {
			const data = await deleteBackgroundImage(id);
			if (id === this.agentDao.getBackgroundId()) {
				this.agentDao.setBackgroundId(-2);
			}
			this.setResponse(IEvent.BACKGROUND, Response.DELETE_BACKGROUND_SUCCESS, data);
		} catch (error) {
			this.setResponse(IEvent.BACKGROUND, Response.DELETE_BACKGROUND_ERROR, error as any);
		} finally {
			this.getBackgroundList();
		}
	}

	public async uploadWaterMark(file: any) {
		const { code, data, message } = await validateImage(file, 5);
		try {
			if (code === 200) {
				const file = await compressFile(data, 0.01, true, 0.92, 120, 67.5);
				const prevImage = await uploadFile(file as File);
				const realImage = await uploadFile(data as File);
				if (prevImage && realImage) {
					if (validateArrayLength(this.agentDao.getWaterMarkList(), 30)) {
						await this.createWaterMark({ url: prevImage.url, abbreviatedUrl: realImage.url, fileName: realImage.name, isDefault: false });
						this.setResponse(IEvent.WATERMARK, Response.CREATE_WATER_MARK_SUCCESS, data);
						return { data: { code: 200, data: { prevImage, realImage }, message: 'uploadWaterMark success' } };
					} else {
						this.setResponse(IEvent.WATERMARK, Response.CREATE_WATER_MARK_COUNT_ERROR, data);
						return { data: { code: 400, data: { prevImage, realImage }, message: 'uploadWaterMark  failed' } };
					}
				} else {
					this.setResponse(IEvent.WATERMARK, Response.CREATE_WATER_MARK_PARAMS_ERROR, data);
					return { data: { code: 400, data: { prevImage, realImage }, message: 'uploadWaterMark  failed' } };
				}
			} else {
				if (code === 501) {
					this.setResponse(IEvent.WATERMARK, Response.FILE_TYPE_ERROR, { code, data, message });
				} else if (code === 502) {
					this.setResponse(IEvent.WATERMARK, Response.FILE_SIZE_ERROR, { code, data, message });
				} else if (code === 503 || code === 504) {
					this.setResponse(IEvent.WATERMARK, Response.IMAGE_SIZE_ERROR, { code, data, message });
				}
			}
		} catch (e) {
			this.setResponse(IEvent.WATERMARK, Response.CREATE_WATER_MARK_ERROR, e as any);
		}
	}

	/** 获取水印列表 */
	public async initWaterMark() {
		try {
			const { data } = await getWaterMarkList({ page: 1, pageSize: 50 });
			if (data.code === 200) {
				this.agentDao.setWaterMarkId(data.data.selectedMarkId || -1);
				const list = data.data.data;
				list.map((item: any) => {
					return { ...item, url: this.configure.replaceStaticUrl(item.url) || '', abbreviatedUrl: this.configure.replaceStaticUrl(item.abbreviatedUrl) || '' };
				});
				this.agentDao.setWaterMarkList(filterWaterMarkList(list));
				this.setResponse(IEvent.WATERMARK, Response.GET_WATER_MARK_LIST_SUCCESS, data.data);
			} else {
				this.setResponse(IEvent.WATERMARK, Response.GET_WATER_MARK_LIST_ERROR, data);
			}
			console.log(data);
		} catch (error) {
			console.log(error);
			this.setResponse(IEvent.WATERMARK, Response.GET_WATER_MARK_LIST_ERROR, error as any);
		}
	}

	/** 创建水印 */
	public async createWaterMark(watermark: { url: string; abbreviatedUrl: string; fileName: string; isDefault: boolean }) {
		try {
			const { data } = await createWaterMark(watermark);
			if (data.code === 200) {
				this.setResponse(IEvent.WATERMARK, Response.CREATE_WATER_MARK_SUCCESS, data.data);
			} else {
				this.setResponse(IEvent.WATERMARK, Response.CREATE_WATER_MARK_ERROR, data);
			}
			console.log(data);
		} catch (error) {
			console.log(error);
			this.setResponse(IEvent.WATERMARK, Response.CREATE_WATER_MARK_ERROR, error as any);
		} finally {
			this.initWaterMark();
		}
	}

	/** 删除水印 */
	public async delWaterMark(id: number) {
		try {
			const { data } = await delWaterMark(id);
			if (id === this.agentDao.getWaterMarkId()) {
				this.agentDao.setWaterMarkId(-1);
			}
			this.setResponse(IEvent.WATERMARK, Response.DELETE_WATER_MARK_SUCCESS, data);
			console.log(data);
		} catch (error) {
			this.setResponse(IEvent.WATERMARK, Response.DELETE_WATER_MARK_ERROR, error as any);
			console.log(error);
		} finally {
			this.initWaterMark();
		}
	}

	/** 应用水印 */
	public async applyWaterMark(id: number) {
		try {
			const { data } = await putWaterMark({ markId: id });
			if (data.code === 200) {
				this.agentDao.setWaterMarkId(id);
				this.setResponse(IEvent.WATERMARK, Response.APPLY_WATER_MARK_SUCCESS, data);
			} else {
				this.setResponse(IEvent.WATERMARK, Response.APPLY_WATER_MARK_ERROR, data);
			}

			console.log(data);
		} catch (error) {
			console.log(error);
			this.setResponse(IEvent.WATERMARK, Response.APPLY_WATER_MARK_ERROR, error as any);
		}
	}

	/** 设置token */
	public setToken(token: string) {
		this.token = token;
	}
	/** 获取sdk内部最新的token */
	public getToken() {
		return getNewToken();
	}

	/** 设置用户登录数据 */
	public setLoginData(loginData: ILoginData) {
		return this.configure.setLoginData(loginData);
	}

	/** 查询坐席小休状态 */
	public async checkedOtherWork() {
		try {
			const { data } = await checkedAgentOtherWork();
			if (data.code === 200) {
				if (data.data) {
					this.configure.setOtherWork({
						...this.configure.otherWork,
						timeoutOtherWork: data.data.timeoutOver ? 'on' : 'off',
						endSessionOtherWork: data.data.sessionOver ? 'on' : 'off',
						timeoutReason: data.data.reasonForTimeoutOver || '',
						endSessionReason: data.data.reasonForSessionOver || '话术整理'
					});
					const userSettings = [...this.configure.userSettings];
					userSettings.forEach(item => {
						if (item.i18nKey === 'auto-otherWork') {
							// item.children[0].status = this.configure.otherWork.endSessionOtherWork;
							item.children[0].status = this.configure.otherWork.timeoutOtherWork;
						}
					});
					this.configure.setUserSettings(userSettings);
				}
				this.setResponse(IEvent.OTHER_WORK, Response.CHECKED_OTHER_WORK_SUCCESS, data);
			} else {
				this.setResponse(IEvent.OTHER_WORK, Response.CHECKED_OTHER_WORK_ERROR, data);
			}
		} catch (error) {
			this.setResponse(IEvent.OTHER_WORK, Response.CHECKED_OTHER_WORK_API_ERROR, error as any);
			console.log(error);
		}
	}

	/**  保存坐席小休状态 */
	public async saveOtherWork() {
		try {
			const otherWork = {
				sessionOver: false,
				timeoutOver: this.configure.otherWork.timeoutOtherWork === 'on',
				reasonForTimeoutOver: this.configure.otherWork.timeoutReason,
				reasonForSessionOver: ''
			};
			const { data } = await saveOtherWork(otherWork);
			if (data.code === 200) {
				const userSettings = [...this.configure.userSettings];
				userSettings.forEach(item => {
					if (item.i18nKey === 'auto-otherWork') {
						// item.children[0].status = this.configure.otherWork.endSessionOtherWork;
						item.children[0].status = this.configure.otherWork.timeoutOtherWork;
					}
				});
				this.configure.setUserSettings(userSettings);
				this.setResponse(IEvent.OTHER_WORK, Response.APPLY_OTHER_WORK_SUCCESS, data);
			} else {
				this.setResponse(IEvent.OTHER_WORK, Response.APPLY_OTHER_WORK_ERROR, data);
			}
		} catch (error) {
			this.setResponse(IEvent.OTHER_WORK, Response.APPLY_BACKGROUND_API_ERROR, error as any);
			console.log(error);
		}
	}

	/** 坐席登出 */
	public async logout() {
		// 设置登录状态为false, 避免处理ams disconnect事件
		this.agentStatus.logged = false;
		if (this.useAsWidget) {
			// post LOGOUT event to parent firstly
			this.setResponse(IEvent.LOGOUT, 0, null);
		}
		try {
			const data: any = await logout();
			this.setResponse(IEvent.LOGOUT, Response.LOGOUT_SUCCESS, data);
		} catch (error) {
			this.setResponse(IEvent.LOGOUT, Response.LOGOUT_ERROR, error as any);
		} finally {
			this.close();
			this.sessionEnd();
			if (!this.agentStatus.checkIn) {
				this.removeCallProgressTimer();
			}
		}
	}

	public notifyOtherAgents = (operationType: string, data: any, messageType: string) => {
		return this.notifyOtherAgentsOperation(operationType, data, messageType, [...this.agentMembers.values()], this.user?.clientId ? this.user?.clientId : '', (content, clientId) => {
			sendCustomizeMessage(content, clientId);
		});
	};

	/** 监听呼叫排队进度 */
	public watchProgress(propgress: { total: number; groups: { groupName: string; groupId: number; waitingNum: number }[] }) {
		this.setCallProgressGroups(propgress.groups);
		this.updateCallProgress(propgress.total);
		this.setResponse(IEvent.CALL_PROGRESS, Response.CHECKED_CALL_PROGRESS_SESSION_ERROR, propgress);
		this.waitingInfoTips = propgress.groups + '';
	}

	/** 事件监听 */
	private systemErrorListener() {
		const onSystemErrorListener = this.systemErrorEvent((error: any) => {
			this.errorHangup(error);
			this.setResponse(IEvent.SYSTEM_ERROR, Response.SYSTEM_ERROR_EVENT, error as any);
		});
		this.saveSessionEventMap(ISessionEventKey.systemError, onSystemErrorListener);
	}

	private onDropListener() {
		this.onDrop((ack: any) => {
			console.log(ack);
			if (ack.code === 401 && ack.reason === 'accountDeleted') {
				this.removeCallProgressTimer();
			}
			this.setResponse(IEvent.ON_DROP, Response.ON_DROP_EVENT, ack as any);
		});
	}

	private streamAddListener() {
		const onStreamAddListener = this.onStreamAdd((streamData: { type: any; data: any }) => {
			const {
				id = '',
				label = '',
				audioOnly,
				clientId,
				videoId,
				isAudioMute,
				isVideoMute,
				customerRole,
				muteStatus,
				streamMode,
				role,
				isScreenSyncMode,
				userName,
				isRobot
			} = filterStreamInfo(streamData);

			const isTeamLeader = userName !== this.user?.userName && this.agentStatus.isChief;
			const client = this.agentController.getSessionClientWithClientID(label);
			if (client) {
				client.setStatus('published');
				client.setStreamInfo({ ...client.getStreamInfo(), id, streamLabel: label, audioOnly, isAudioMute, isVideoMute, streamMode, isScreenSyncMode, muteStatus });
				client.setVideoInfo({ ...client.getVideoInfo(), id: label, streamMode: audioOnly ? 'audio' : 'video', micMute: isAudioMute });
				client.setTeamLeader(isTeamLeader);
				this.setResponse(IEvent.UPDATE_CLIENT_INFO, Response.UPDATE_CLIENT_INFO, client);
			} else {
				const newClient = new Client({ clientId, isRobot, customerRole: customerRole || '', role, userName, status: 'published', isTeamLeader: isTeamLeader });
				newClient.setStreamInfo({ ...newClient.getStreamInfo(), id, streamLabel: label, audioOnly, isAudioMute, isVideoMute, streamMode, isScreenSyncMode, muteStatus });
				newClient.setVideoInfo({ ...newClient.getVideoInfo(), id: label, streamMode: audioOnly ? 'audio' : 'video', micMute: isAudioMute });
				this.agentController.saveSessionClient(newClient);
				this.setResponse(IEvent.STREAM_ADD, Response.STREAM_ADD_EVENT, newClient);
			}

			/** 处理流加入 */
			this.onStreamAddEvent({
				id,
				label,
				audioOnly,
				clientId,
				videoId,
				isAudioMute,
				isVideoMute,
				muteStatus,
				streamMode,
				customerRole,
				role,
				isScreenSyncMode,
				userName,
				isRobot,
				networkStatus: ''
			});
		});

		this.saveSessionEventMap(ISessionEventKey.onStreamAdd, onStreamAddListener);
	}

	private streamEndListener() {
		const onStreamEndListener = this.onStreamEnd((streamData: any) => {
			let stream = filterStreamInfo({ type: streamData.type, data: streamData.data.streamInfo });
			this.agentController.removeSessionClientWithLabel(stream.label);
			console.log('streamEndListener:', stream);
			/** 处理流结束 */
			this.onStreamEndEvent(stream as any);
			this.setResponse(IEvent.STREAM_END, Response.STREAM_END_EVENT, streamData as any);
		});
		this.saveSessionEventMap(ISessionEventKey.onStreamEnd, onStreamEndListener);
	}

	private customerJoinSessionListener() {
		const onCustomerJoinSessionListener = this.onCustomerJoinSession((info: any) => {
			console.log(info);
			/** 处理访客加入会话 */
			this.onCustomerJoinSessionEvent(info);
			this.setResponse(IEvent.CUSTOMER_JOIN_SESSION, Response.CUSTOMER_JOIN_EVENT, info as any);
		});
		this.saveSessionEventMap(ISessionEventKey.onCustomerJoinSession, onCustomerJoinSessionListener);
	}

	private customerQuitSessionListener() {
		const onCustomerQuitSessionListener = this.onCustomerQuitSession(async (info: any) => {
			console.log(info);
			/** 处理访客离开会话 */
			this.onCustomerQuitSessionEvent(info);
			console.log(this.customerStreams, this.allMediaStream, this.largeStreams);
			const stream = this.allMediaStream.find(item => item.clientId === info.data.id);
			if (stream) {
				this.renderedStreamMap.delete(stream.videoId);
				this.largeStreams = [];
			}
			if (this.getCustomerMediaStream().length === 0 && !this.isIMSession) {
				// 访客因为音视频授权失败，退出会话
				if (info.data?.reason?.code === '60022') {
					updateMediaRenderStatus(this.sessionId, false);
				}
				await this.hangup({ code: 200, reason: 'session end', type: 'customer-quit' });
			}
			this.setResponse(IEvent.CUSTOMER_QUIT_SESSION, Response.CUSTOMER_QUIT_EVENT, info as any);
		});
		this.saveSessionEventMap(ISessionEventKey.onCustomerQuitSession, onCustomerQuitSessionListener);
	}

	private agentJoinSessionListener() {
		const onAgentJoinSessionListener = this.onAgentJoinSession((info: any) => {
			/** 处理坐席加入会话 */
			this.onAgentJoinSessionEvent(info);
			this.setResponse(IEvent.AGENT_JOIN_SESSION, Response.AGENT_JOIN_EVENT, info as any);
		});
		this.saveSessionEventMap(ISessionEventKey.onAgentJoinSession, onAgentJoinSessionListener);
	}

	private agentQuitSessionListener() {
		const onAgentQuitSessionListener = this.onAgentQuitSession((info: any) => {
			/** 处理坐席离开 */
			this.onAgentQuitSessionEvent(info);
			this.setResponse(IEvent.AGENT_QUIT_SESSION, Response.AGENT_QUIT_EVENT, info as any);
		});
		this.saveSessionEventMap(ISessionEventKey.onAgentQuitSession, onAgentQuitSessionListener);
	}

	private amsConnectListener() {
		this.amsConnect((status: any) => {
			// 如果已登出，不做处理
			if (!this.agentStatus.logged) {
				return;
			}
			console.log('amsConnect status', status);
			if (status === 'online') {
				this.getSessionMembers();
			}
			if (status === 'online' || status === 'connected') {
				if (!this.callProgressTime) {
					let timer = setInterval(() => {
						getQueueInfo(
							progress => this.watchProgress(progress),
							() => {
								this.removeCallProgressTimer();
							}
						);
					}, 2000);
					this.setCallProgressTimer(timer);
				}
			}
			Network.setLocalAmsStatus(status);
			if (['online', 'offline'].includes(status)) {
				Network.setLocalCcsStatus(status);
			}

			// console.log('amsConnect:', status);

			if (['reconnect_failed', 'reconnecting', 'ping-timeout', 'ping-connected', 'offline'].includes(status)) {
				this.removeCallProgressTimer();
				this.setCallProgressTimer(null);
				this.amsNetworkTips = 'disconnect-from-dispatch-system-reconnect';
				if (status === 'reconnect_failed' && !this.sessionId) {
					this.amsNetworkTips = 'disconnect-from-dispatch-system-relogin';
				}
			}

			if (['connected', 'online', 'ping-connected'].includes(status)) {
				if (!this.callProgressTime) {
					let timer = setInterval(() => {
						getQueueInfo(
							progress => this.watchProgress(progress),
							() => {
								this.removeCallProgressTimer();
							}
						);
					}, 3000);
					this.setCallProgressTimer(timer);
				}
				this.amsNetworkTips = '';
			}
			this.setResponse(IEvent.AMS, Response.AMS_CONNECT_EVENT, status as any);
		});
	}

	private ccsErrorListener() {
		this.ccsError((resp: any) => {
			this.setResponse(IEvent.CCS_ERROR, Response.CCS_ERROR_EVENT, resp as any);
		});
	}

	private onRingListener() {
		this.onRing((resp: ICallUserData) => {
			this.setRingData(resp);
			this.setResponse(IEvent.ON_RING, Response.ON_RING_EVENT, resp as any);
		});
	}

	private onCancelRingListener() {
		this.onCancelRing((resp: any) => {
			this.setResponse(IEvent.CANCEL_RING, Response.ON_CANCEL_RING_EVENT, resp as any);
		});
	}

	private onPublishMediaStatusListener() {
		this.onPublishMediaStatus((resp: any) => {
			this.setResponse(IEvent.PUBLISH_MEDIA_STATUS, Response.PUBLISH_MEDIA_STATUS_EVENT, resp as any);
		});
	}
	private onRenderMediaStatusListener() {
		this.onRenderMediaStatus((resp: any) => {
			this.setResponse(IEvent.RENDER_MEDIA_STATUS, Response.RENDER_MEDIA_STATUS_EVENT, resp as any);
		});
	}

	private ccsDropListener() {
		this.onCcsDrop(async (resp: any) => {
			Network.setLocalCcsStatus('reconnect_failed');
			this.setResponse(IEvent.CCS_DROP, Response.CCS_DROP_EVENT, resp as any);
		});
	}

	private onOtherReconnectingListener() {
		this.onOtherReconnecting((resp: any) => {
			const { id } = resp.data;
			Network.setRemoteStatus({ id, status: 'reconnecting' });
			this.setResponse(IEvent.OTHER_RECONNECTING, Response.OTHER_RECONNECTING_EVENT, resp as any);
		});
	}

	private onOtherResumeConnectListener() {
		this.onOtherResumeConnect((resp: any) => {
			const { id } = resp.data;
			Network.setRemoteStatus({ id: id, status: 'connected' });
			this.setResponse(IEvent.OTHER_RESUME_RECONNECT, Response.OTHER_RESUME_RECONNECT_EVENT, resp as any);
		});
	}

	private onCcsResumeSuccessListener() {
		this.onCcsResumeSuccess((resp: any) => {
			this.setResponse(IEvent.ON_CCS_RESUME_SUCCESS, Response.ON_CCS_RESUME_SUCCESS_EVENT, resp as any);
		});
	}

	public onSessionRecordCrashListener() {
		this.onSessionRecordCrash((resp: any) => {
			this.setResponse(IEvent.ON_SESSION_RECORD_CRASH, Response.ON_SESSION_RECORD_CRASH_EVENT, resp as any);
		});
	}

	private onSessionConnectStatusListener() {
		this.onSessionConnectStatus((resp: any) => {
			if (resp === 'connected') {
				this.getSessionMembers();
			}
			Network.setLocalCcsStatus(resp);
			this.setResponse(IEvent.SESSION_CONNECT_STATUS, Response.SESSION_CONNECT_STATUS_EVENT, resp as any);
		});
	}

	private onTextMessageListener() {
		this.onTextMessage((resp: any) => {
			this.setResponse(IEvent.TEXT_MESSAGE, Response.TEXT_MESSAGE_EVENT, resp as any);
		});
	}

	private onResourceMessageListener() {
		this.onResourceMessage((resp: any) => {
			this.setResponse(IEvent.RESOURCE_MESSAGE, Response.RESOURCE_MESSAGE_EVENT, resp as any);
		});
	}

	private onCustomizeMessageListener() {
		this.onCustomizeMessage((resp: any) => {
			console.log('onCustomizeMessage:', resp);

			if (resp.data.businessType === 'notice_media_progress') {
				let client = this.agentController.getSessionClientWithLabel(resp.data.label);
				// 如果是坐席端开画进度，需要判断是否已经发布
				let isPublished = false;
				if (client && client.status === 'published') {
					isPublished = true;
				}
				this.agentController.setSessionClient(resp, isPublished);
				client = this.agentController.getSessionClientWithLabel(resp.data.label);
				console.log('onCustomizeMessage:', client);
				if (client) {
					this.setResponse(IEvent.STREAM_ADD, Response.STREAM_ADD_EVENT, client);
				}
			}
			this.setResponse(IEvent.CUSTOMIZE_MESSAGE, Response.CUSTOMIZE_MESSAGE_EVENT, resp as any);
		});
	}

	private onInvitationProgressListener() {
		this.onInvitationProgress((resp: any) => {
			this.setResponse(IEvent.INVITATION_PROGRESS, Response.INVITATION_PROGRESS_EVENT, resp as any);
		});
	}

	private onVariableChangeListener() {
		this.onVariableChange((resp: any) => {
			console.log(resp, 'onVariableChange');
			this.setResponse(IEvent.VARIABLE_CHANGE, Response.VARIABLE_CHANGE_EVENT, resp as any);
		});
	}

	private onSyncMessageListener() {
		this.onSyncMessage((resp: any) => {
			console.log(resp, 'onSyncMessage');
			this.setResponse(IEvent.SYNC_MESSAGE, Response.SYNC_MESSAGE_EVENT, resp as any);
		});
	}

	private onRealTimeQualityListener() {
		this.onRealTimeQuality((resp: any) => {
			console.log(resp, 'onRealTimeQuality');
			this.setResponse(IEvent.REAL_TIME_QUALITY, Response.REAL_TIME_QUALITY_EVENT, resp as any);
		});
	}

	private onResetStatusListener() {
		this.onResetStatus((resp: any) => {
			console.log(resp, 'onResetStatusListener');
			if (resp.status === 'otherWork') {
				this.setAgentStatus({ ...this.agentStatus, otherWork: resp.conditionOfOtherwork === 'sessionOver' || resp.conditionOfOtherwork === 'timeoutOver', ready: false });
			}
			this.setResponse(IEvent.ON_RESET_STATUS, Response.ON_RESET_STATUS_EVENT, resp as any);
		});
	}

	private onSystemRecordUpdateListener() {
		this.onSystemRecordUpdate((resp: any) => {
			this.setResponse(IEvent.ON_SYSTEM_RECORD_UPDATE, Response.ON_SYSTEM_RECORD_UPDATE_EVENT, resp as any);
			if (resp?.status === 'start') {
				this.setRecordingData({ ...this.recordingPoint, recordingId: resp.recordId });
				this.setRecordingAlertInformation({ systemRecordingId: resp.recordId, type: 'system' });
			}
		});
	}

	private onSyncSessionSummaryListener() {
		this.onSyncSessionSummary((resp: any) => {
			console.log(resp, 'onSyncSessionSummary');
			this.setResponse(IEvent.ON_SYNC_SESSION_SUMMARY, Response.ON_SYNC_SESSION_SUMMARY_EVENT, resp as any);
		});
	}

	private getRenderStream(videoId: string): MediaStream | null {
		if (!videoId) return null;
		const container = document.getElementById(videoId) as HTMLVideoElement;
		const stream = container.srcObject as MediaStream;
		return stream;
	}

	private onbeforeunload() {
		console.log('onbeforeunload');
		window.addEventListener('beforeunload', (e: any) => {
			// e = e || window.event;
			// //兼容IE8和Firefox 4之前的版本
			// if (e) {
			// 	e.returnValue = '关闭提示';
			// }

			// // Chrome, Safari, Firefox 4+, Opera 12+ , IE 9+
			// return '';
			try {
				this.fetchUserLeave();
				// this.userPageClose();
			} catch (error) {
				console.log(error);
			} finally {
				this.setResponse(IEvent.PAGE_LEAVE, Response.PAGE_LEAVE_EVENT, null);
			}
		});
	}

	private onunload() {
		window.addEventListener('unload', (e: any) => {
			try {
				this.fetchUserLeave();
				// this.userPageClose();
			} catch (error) {
				console.log(error);
			} finally {
				this.setResponse(IEvent.PAGE_LEAVE, Response.PAGE_LEAVE_EVENT, e as any);
			}
		});
		console.log('onunload');
	}

	private userPageClose() {
		closePage();
	}

	private removeSessionListenerEvent() {
		this.clearSessionEvent();
	}

	/** 页面离开事件 */
	public addPageLeaveEvent() {
		this.onbeforeunload();
		this.onunload();
	}

	public removePageLeaveEvent() {
		window.removeEventListener('beforeunload', (e: any) => {
			console.warn('remove onbeforeunload success');
		});
		window.removeEventListener('unload', (e: any) => {
			console.warn('remove onunload success');
		});
	}

	/** 登录系统事件监听 */
	private initBaseEvent() {
		this.addPageLeaveEvent();
		/** 监听 onDrop 事件 */
		this.onDropListener();
		/** 监听系统错误事件 */
		this.systemErrorListener();
		/** ams 连接状态事件 */
		this.amsConnectListener();
		/** 监听坐席振铃事件 */
		this.onRingListener();
		/** 监听取消振铃事件 */
		this.onCancelRingListener();
		/** 监听坐席小休状态 */
		this.onResetStatusListener();
	}

	/** 加入会话前事件监听 */
	public initJoinSessionEvent() {
		/** 监听自定义消息事件 */
		this.onCustomizeMessageListener();
		/** 监听 ccs 错误事件 */
		this.ccsErrorListener();
		/** 监听流加入事件 */
		this.streamAddListener();
		/** 监听流离开事件 */
		this.streamEndListener();
		/** 监听坐席加入会话开事件 */
		this.agentJoinSessionListener();
		/** 监听坐席离开会话开事件 */
		this.agentQuitSessionListener();
		/** 监听访客加入会话开事件 */
		this.customerJoinSessionListener();
		/** 监听访客离开会话开事件 */
		this.customerQuitSessionListener();
		/** 监听订阅流网络数据 */
		this.onRenderMediaStatusListener();
		/** 监听发布流网络数据 */
		this.onPublishMediaStatusListener();
	}

	/** 加入会话后事件监听 */
	public initJoinedSessionEvent() {
		/** 监听强踢事件 */
		this.ccsDropListener();
		/** 监听其他用户重连事件 */
		this.onOtherReconnectingListener();
		this.onOtherResumeConnectListener();
		/** 监听坐席转接进度 */
		this.onInvitationProgressListener();
		/** 监听会话重连事件 */
		this.onSessionConnectStatusListener();
		/** 监听文字消息事件 */
		this.onTextMessageListener();

		/** 监听资源消息事件 */
		this.onResourceMessageListener();
		/** 监听变量更新 */
		this.onVariableChangeListener();
		/** 监听业务指令消息留痕 */
		this.onSyncMessageListener();
		/** 监听实时质检结果返回 */
		this.onRealTimeQualityListener();
		/** 监听升降级的事件 */
		this.onUpgradeListener();

		this.onCcsResumeSuccessListener();
		/** 监听系统录像变化事件 */
		this.onSystemRecordUpdateListener();
		/** 监听会话总结变化事件 */
		this.onSyncSessionSummaryListener();
	}

	/** 设置坐席振铃数据 */
	private setRingData(data: ICallUserData) {
		const { userData, sessionId = '', invitationId = '', bizScenarioId = '', media } = data;
		this.setSessionId(sessionId);
		window.sessionStorage.setItem('sessionID', sessionId);
		this.setInvitationId(invitationId);
		this.setBizScenarioId(bizScenarioId);
		this.setUserCallData(userData);
		const { microphoneStatus = 'unmute', receiveMediaType = 'video', callMediaType = 'video', inviteMediaType } = userData;
		let type = receiveMediaType;
		if (media === 'imUpgradeAudio') {
			type = 'audio';
		} else if (media === 'imUpgradeVideo') {
			type = 'video';
		}
		if (inviteMediaType) {
			type = inviteMediaType;
		}

		this.setAcceptCallMode({ microphoneStatus, receiveMediaType: type, callMediaType });
		if (bizScenarioId) {
			this.fetchGroupWithBizscenariosID(parseInt(this.bizScenarioId));
		}
		clog.setSessionId(sessionId);
	}

	public setRecordingAlertInformation(data: { systemRecordingId?: string | number; regionalScreenRecordingId?: string | number; screenRecordingId?: string | number; type?: string }) {
		this.setRecordingAlert({
			...this.recordingAlert,
			systemRecordingId: data.systemRecordingId ? data.systemRecordingId : this.recordingAlert.systemRecordingId,
			regionalScreenRecordingId: data.regionalScreenRecordingId ? data.regionalScreenRecordingId : this.recordingAlert.regionalScreenRecordingId,
			screenRecordingId: data.screenRecordingId ? data.screenRecordingId : this.recordingAlert.screenRecordingId
		});
		if (data.type === 'system' && this.isAutoSystemRecord) {
			// 自动双录时再处理
			this.setResponse(IEvent.RECORDING_ALERT, Response.RECORDING_ALERT_EVENT, this.recordingAlert as any);
		}
	}

	/** 设置接听后返回得数据 */
	private setAcceptMediaCallData(data: IAnswerMediaData) {
		const { sessionData } = data;
		const { recordingId, clientId, members, roomId } = sessionData;
		console.log('session members:', members);
		//系统录像recordingId
		this.setRecordingData({ ...this.recordingPoint, recordingId });
		// this.setRecordingAlertInformation({ systemRecordingId: recordingId, type: 'system' });
		this.setClientID(clientId);
		const agent = members.find(item => item.id === clientId);
		this.setUser({ ...this.user, clientId, userName: agent?.user.name });
		this.setSessionMembers(members);
		this.setRoomId(roomId);
	}

	/** 系统错误挂断会话 */
	private async errorHangup(error: { code: number }) {
		console.log('error hang up:', error);
		// 1005 mcu异常，不执行挂断。
		if (error.code === 1006 || error.code === 1007) {
			await this.hangup({ code: error.code, reason: 'system error' });
		}
	}

	/** 获取用户配置参数 */
	private async initUserProfile() {
		await this.checkedOtherWork();
		await this.getBackgroundList();
		this.agentDao.setWaterMarkList([]);
	}

	private setResponse(event: IEvent, code: Code, response: object | null) {
		let data = Response.creteResponseWithCode(code as number, response);
		// 统一错误处理
		if (event === IEvent.BACKGROUND) {
			backgroundImageRespone(code as number);
		} else if (event === IEvent.WATERMARK) {
			watermarkImageRespone(code as number);
		}
		EventEmit.setServiceEventListener(event, data);
		clog.error(code as number, response);
	}

	private fetchUserLeave() {
		const url = `${this.configure.serviceUrl}/ivcs/api/v1/agents/offline`;
		const data = { agentId: this.logAmsId, sessionId: this.sessionId, clientId: this.clientID };
		const headers = new Headers();
		headers.append('content-type', 'application/json');
		headers.append('x-access-token', this.token);
		console.log('page leave data:', data);

		fetch(url, {
			method: 'POST',
			headers: headers,
			body: JSON.stringify(data),
			keepalive: true
		});
		this.logAmsId = '';
	}

	public entryOtherPage(target: Tentry) {
		this.setResponse(IEvent.DOM_EVENT, Response.DOM_EVENT, { event: 'click', target: target });
	}

	public close() {
		this.setAgentStatus({ ...this.agentStatus, logged: false, isChief: false, checkIn: false, otherWork: false, ready: false, afterWork: false });
		this.setCheckedGroups([]);
		this.removeEventListener();
		this.removeCallProgressTimer();
	}

	private onUpgradeListener() {
		this.onUpgrade((resp: any) => {
			const { type } = resp.data;
			console.warn('onUpgradeListener ', resp, this.acceptCallMode.callMediaType);
			if (type === 'request-upgrade') {
				const { media } = resp.data;
				this.setAcceptCallMode({ microphoneStatus: 'unmute', receiveMediaType: media, callMediaType: this.acceptCallMode.callMediaType });
			} else if (type === 'accept-upgrade') {
				const { roomId, recordingId, media } = resp.data;
				this.setRoomId(roomId);
				this.setRecordingData({ ...this.recordingPoint, recordingId });
				//系统录像recordingId
				// this.setRecordingAlertInformation({ systemRecordingId: recordingId, type: 'system' });
				this.setAcceptCallMode({ microphoneStatus: 'unmute', receiveMediaType: media, callMediaType: media });
			}
			this.setResponse(IEvent.ON_UPGRADE, Response.ON_UPGRADE_EVENT, resp.data as any);
		});
	}

	public async startVideo() {
		try {
			if (!validateAms(Network.amsStatus)) {
				this.setResponse(IEvent.ANSWER, Response.ANSWER_ERROR_AMS_EXCEPTION, null);
				return { code: 400, message: 'answer failed ams connected failed', data: null };
			}

			const { loginData } = this.configure;
			console.log(this.acceptCallMode?.callMediaType, 'this.acceptCallMode?.callMediaType');

			const data = await startVideo(loginData.username, this.acceptCallMode?.callMediaType || 'video');
			if (data?.code === 200) {
				const { publicationId } = data.data;
				this.setPublicationId(publicationId);
				this.saveCurrentAgentStream();
				this.onSessionRecordCrashListener();
				this.setResponse(IEvent.START_VIDEO, Response.START_VIDEO_SUCCESS, data.data);
			} else {
				this.setResponse(IEvent.START_VIDEO, Response.START_VIDEO_ERROR, data);
			}
		} catch (error) {
			console.warn('startVideo ', error);
			this.setResponse(IEvent.START_VIDEO, Response.START_VIDEO_ERROR, error as any);
		}
	}

	public async answerImCall() {
		try {
			const data = await answerImCall();
			console.warn('answerImCall ', data);
			/** 监听加入会话前事件 */
			this.initJoinSessionEvent();
			const { clientId, members, media } = data.sessionData;
			this.setUser({ ...this.user, clientId });
			this.setClientID(clientId);
			this.setSessionMembers(members);
			/** 监听加入会话后事件 */
			this.initJoinedSessionEvent();
			this.setResponse(IEvent.ANSWER, Response.ANSWER_SUCCESS, data.data);
			// imUpgradeAudio
			if (media === 'imUpgradeAudio') {
				// upgrade to audio
				this.setAcceptCallMode({ microphoneStatus: 'unmute', receiveMediaType: 'audio', callMediaType: 'audio' });
				this.startVideo();
			} else if (media === 'imUpgradeVideo') {
				// upgrade to video
				this.setAcceptCallMode({ microphoneStatus: 'unmute', receiveMediaType: 'video', callMediaType: 'video' });
				this.startVideo();
			}
		} catch (error) {
			console.warn('answerImCall ', error);
			this.setResponse(IEvent.ANSWER, Response.ANSWER_ERROR, error as any);
		}
	}

	public async requestUpgrade(media: string, toWhom: string) {
		return new Promise(async (resolve, reject) => {
			try {
				const data = await requestUpgrade(media, toWhom);
				this.setResponse(IEvent.REQUEST_UPGRADE, Response.REQUEST_UPGRADE_SUCCESS, { media: media });
				resolve(data);
			} catch (error) {
				console.warn('requestUpgrade ', error);
				this.setResponse(IEvent.REQUEST_UPGRADE, Response.REQUEST_UPGRADE_ERROR, { media: media, error: error });
				reject(error);
			}
		});
	}

	public async acceptUpgrade(media: IStreamMode): Promise<boolean> {
		return new Promise(async (resolve, reject) => {
			try {
				const data = await acceptUpgrade(media);
				const { recordingId, roomId } = data;
				this.setRoomId(roomId);
				this.setRecordingData({ ...this.recordingPoint, recordingId });
				//系统录像recordingId
				// this.setRecordingAlertInformation({ systemRecordingId: recordingId, type: 'system' });
				this.setAcceptCallMode({
					callMediaType: media,
					receiveMediaType: media,
					microphoneStatus: 'unmute'
				});
				this.setResponse(IEvent.ACCEPT_UPGRADE, Response.ACCEPT_UPGRADE_SUCCESS, data);
				resolve(data);
			} catch (error) {
				console.warn('acceptUpgrade ', error);
				this.setResponse(IEvent.ACCEPT_UPGRADE, Response.ACCEPT_UPGRADE_ERROR, error as any);
				reject(error);
			}
		});
	}

	public async rejectUpgrade(media: string, reason: any) {
		return new Promise(async (resolve, reject) => {
			try {
				const data = await rejectUpgrade(media, reason);
				resolve(data);
			} catch (error) {
				console.warn('rejectUpgrade ', error);
				this.setResponse(IEvent.REJECT_UPGRADE, Response.REJECT_UPGRADE_ERROR, error as any);
				reject(error);
			}
		});
	}

	public async cancelUpgrade(reason = 'normal', media?: string) {
		return new Promise(async (resolve, reject) => {
			try {
				const data = await cancelUpgrade(reason, media);
				resolve(data);
			} catch (error) {
				console.warn('cancelUpgrade ', error);
				this.setResponse(IEvent.CANCEL_UPGRADE, Response.CANCEL_UPGRADE_ERROR, error as any);
				reject(error);
			}
		});
	}

	public async getSessionMembers() {
		try {
			const data = await getSessionMembers();
			this.setResponse(IEvent.GET_SESSION_MEMBERS, Response.GET_SESSION_MEMBERS_SUCCESS, data.data as any);
		} catch (error) {
			console.log(error, 'get session members error');
			this.setResponse(IEvent.GET_SESSION_MEMBERS, Response.GET_SESSION_MEMBERS_ERROR, error as any);
		}
	}

	public getLanguage() {
		return this.configure.getLanguage();
	}

	public setLanguage(language: 'zh' | 'zh-TW' | 'en-US') {
		return this.configure.setLanguage(language);
	}

	public getVideoDeviceID() {
		return this.mediaDeviceController.getVideoInputDeviceID();
	}

	public getAudioDeviceID() {
		return this.mediaDeviceController.getAudioInputDeviceID();
	}

	public testMic() {
		return this.mediaDeviceController.testMic();
	}

	public testCamera() {
		return this.mediaDeviceController.testCamera();
	}

	public getDefaultAudioInputDeviceID() {
		return this.mediaDeviceController.getDefaultAudioInputDeviceID();
	}

	public getSpeakerDeviceID() {
		return this.mediaDeviceController.getSpeakerDeviceID();
	}

	public getDefaultSpeaker() {
		return this.mediaDeviceController.getDefaultSpeaker();
	}

	public setAudioInputDeviceId(deviceID: string | undefined) {
		return this.mediaDeviceController.setAudioInputDeviceId(deviceID);
	}

	public setVideoInputDeviceId(deviceID: string | undefined) {
		return this.mediaDeviceController.setVideoInputDeviceId(deviceID);
	}

	public setAudioOutputDeviceId(deviceID: string | undefined) {
		return this.mediaDeviceController.setAudioOutputDeviceId(deviceID);
	}

	public getAudioDevices() {
		return this.mediaDeviceController.getAudioDevices();
	}

	public getVideoDevices() {
		return this.mediaDeviceController.getVideoDevices();
	}

	public getSpeakerDevices() {
		return this.mediaDeviceController.getSpeakerDevices();
	}

	public updateStreamWithDeviceID(videoId: string, deviceId: string) {
		return this.mediaStreamController.updateStreamWithDeviceID(videoId, deviceId);
	}

	public setInputDefaultDeviceIDWithSteam(stream: MediaStream) {
		return this.mediaDeviceController.setInputDefaultDeviceIDWithSteam(stream);
	}

	public createLocalStreamWithConstraints(constraints: MediaStreamConstraints) {
		return this.mediaDeviceController.createLocalStream(constraints);
	}

	public stopLocalStream() {
		return this.mediaDeviceController.stopLocal();
	}

	public switchSpeaker(videoId: string, deviceId: string) {
		return this.mediaDeviceController.switchSpeaker(videoId, deviceId);
	}

	public findDeviceWithDevicID(deviceID: string) {
		return this.mediaDeviceController.findDeviceWithDevicID(deviceID);
	}

	public getAllGroupScene() {
		return this.agentController.getAllGroupScenes();
	}

	public setAllGroupScene(scenes: Scene[]) {
		return this.agentController.setAllGroupScene(scenes);
	}

	public getGroupSkill() {
		return this.agentController.getAllGroupSkill();
	}

	public sendBusiness(cmd: BusinessCmd) {
		return this.agentController.sendBusiness(cmd);
	}

	public fetchAllGroupsWithOrg() {
		return this.agentController.fetchAllGroupsWithOrg();
	}

	public fetchGroupSkill() {
		return this.agentController.fetchGroupSkill();
	}

	public getUserMediaDevices() {
		return this.mediaDeviceController.getUserMediaDevices();
	}

	public getTransferHeaderOptions() {
		return this.agentController.getTransferHeaderOptions();
	}

	public async fetchGroupWithBizscenariosID(id: number, isTransfer = false) {
		await this.agentController.fetchGroupWithBizscenariosID(id, isTransfer);
	}

	public getAllPdffiles() {
		return this.businessController.getPdfFiles().map(item => ({ ...item, url: this.configure.replaceStaticUrl(item.url) }));
	}

	public getAllVideoFiles() {
		return this.businessController.getVideoFiles().map(item => ({ ...item, url: this.configure.replaceStaticUrl(item.url) }));
	}

	public getTTSTalks() {
		return this.businessController.getTTSTalks();
	}

	public fetchTTSTalksWithPageSize(params: { scenId: string | number; page: number; pageSize: number }) {
		return this.businessController.fetchTTSTalksWithPageSize(params);
	}

	public fetchBusinessMaterialWithPageSize(params: { scenId: string | number; type: 'document' | 'video'; page: number; pageSize: number }) {
		return this.businessController.fetchBusinessMaterialWithPageSize(params);
	}

	public fetchBizscenariosAgents(scenId: string) {
		return this.agentController.fetchBizscenariosAgents(scenId);
	}
	public getBizscenariosAgents() {
		return this.agentController.getBizscenariosAgents();
	}

	public getFormDetail(followId: string) {
		return this.businessController.getFormDetail(followId);
	}

	public insertFormDetail(clientId: string, form: IFormBusiness) {
		return this.businessController.insertFormDetail(clientId, form);
	}

	public clearFormDetail() {
		return this.businessController.clearFormDetail();
	}

	public getClientForms(clientId: string) {
		return this.businessController.getClientForms(clientId);
	}

	public getSessionClientWithClientID(clientId: string) {
		return this.agentController.getSessionClientWithClientID(clientId);
	}

	public getSessionClientWithLabel(label: string) {
		return this.agentController.getSessionClientWithLabel(label);
	}

	public removeSessionClientWithLabel(label: string) {
		return this.agentController.removeSessionClientWithLabel(label);
	}

	public getRenderedLabel(label: string) {
		return this.renderedLabel.get(label);
	}
	public setRenderedLabel(label: string, data: { label: string; id: string }) {
		this.renderedLabel.set(label, data);
	}
	// set log level
	public setLogLevel(level: number) {
		super.setLogLevel(level);
		Agent.logger.setLevel(level);
	}

	public getHumanflowSteps() {
		return this.agentController.getHumanflowSteps();
	}

	/**
	 * 推送客户标注的响应数据，拒绝/结束，设备宽高
	 * @param data
	 */
	public sendCustomerViewMarkEventData(data: any) {
		console.log('sendCustomerViewMarkEventData:', data);
		this.setResponse(IEvent.CUSTOMER_VIEW_MARK, Response.CUSTOMER_VIEW_MARK_EVENT, data as any);
	}

	/**
	 * 会话小结是否开启
	 * @returns
	 */
	public isSessionSummaryOn() {
		return this.agentController.isSessionSummaryOn();
	}

	public getHumanAgentCount() {
		let count = 0;
		this.agentMembers.forEach((value: any) => {
			console.log('getHumanAgentCount:', value);
			if (!value.isRobot && value.role === 'agent') {
				count++;
			}
		});
		return count;
	}

	public isFirstHumanAgent() {
		let first = false;
		for (let [key, value] of this.agentMembers) {
			// console.log(`${key}: `, value, this.clientID, this.user?.clientId);
			if (!value?.isRobot) {
				first = value.clientId === this.clientID || value.clientId === this.user?.clientId;
				return first;
			}
		}
		return first;
	}

	/** 添加特定事件的一个监听 */
	public addListener(event: string, ack: (info: any) => void) {
		EventEmit.addListener(event, ack);
	}

	/** 移除特定事件的一个监听 */
	public removeListener(event: string, listener: any) {
		EventEmit.removeListener(event, listener);
	}

	/** 坐席完成会话小结内容，通知给会话中的其他坐席 */
	public async syncSessionSummary(data: any, toWhom: string) {
		await syncSessionSummary(data, toWhom);
	}

	/** 会话小结内容 */
	public getSummaryList() {
		return this.agentController.getSummaryList();
	}

	public async getUnfinishedSummary() {
		const count = await this.agentController.fetchUnfinishedSummaryStatus();
		this.hasUnfinishedSummary = count > 0 ? true : false;
		// event
		console.log('getUnfinishedSummary:', this.hasUnfinishedSummary);

		this.setResponse(IEvent.ON_NEED_DO_SUMMARY_CHANGE, Response.ON_NEED_DO_SUMMARY_CHANGE, { hasUnfinishedSummary: this.hasUnfinishedSummary });
	}

	/** 显示修改密码窗口 */
	public showChangePasswordModal() {
		this.setResponse(IEvent.MODIFY_PASSWORD, Response.MODIFY_PASSWORD_EVENT, null);
	}

	/** 需要更新密码 */
	public needUpdatePassword(needUpdatePassword: string) {
		this.setResponse(IEvent.NEED_UPDATE_PASSWORD, Response.NEED_UPDATE_PASSWORD_EVENT, { needUpdatePassword });
	}
}

export default new Agent();
